package com.zenithmind.mall.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.context.UserContext;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.mall.mapper.CouponMapper;
import com.zenithmind.mall.pojo.dto.CouponDTO;
import com.zenithmind.mall.pojo.entity.Coupon;
import com.zenithmind.mall.pojo.query.CouponQuery;
import com.zenithmind.mall.pojo.vo.CouponVO;
import com.zenithmind.mall.service.CouponManagementService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 优惠券管理服务实现类 - 遵循单一职责原则，专门负责优惠券管理操作
 * 
 * @author ZenithMind Team
 * @since 2025-07-03
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CouponManagementServiceImpl extends ServiceImpl<CouponMapper, Coupon> 
        implements CouponManagementService {

    private final CouponMapper couponMapper;

    @Override
    public PageResult<CouponVO> getCouponPage(CouponQuery query) {
        Page<Coupon> page = new Page<>(query.getCurrent(), query.getSize());
        
        LambdaQueryWrapper<Coupon> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Coupon::getIsDeleted, 0)
               .like(StringUtils.hasText(query.getName()), Coupon::getName, query.getName())
               .eq(query.getType() != null, Coupon::getType, query.getType())
               .eq(query.getStatus() != null, Coupon::getStatus, query.getStatus())
               .ge(query.getStartTime() != null, Coupon::getStartTime, query.getStartTime())
               .le(query.getEndTime() != null, Coupon::getEndTime, query.getEndTime())
               .orderByDesc(Coupon::getCreateTime);

        Page<Coupon> result = page(page, wrapper);
        
        List<CouponVO> voList = result.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());

        return new PageResult<>(voList, result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    public CouponVO getCouponById(String id) {
        Coupon coupon = getById(id);
        if (coupon == null) {
            throw new BusinessException("优惠券不存在");
        }
        return convertToVO(coupon);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createCoupon(CouponDTO couponDTO) {
        validateCouponData(couponDTO);
        
        Coupon coupon = new Coupon();
        BeanUtils.copyProperties(couponDTO, coupon);
        coupon.setCreateBy(UserContext.getUserId());
        
        // 设置默认值
        if (coupon.getReceivedCount() == null) {
            coupon.setReceivedCount(0);
        }
        if (coupon.getUsedCount() == null) {
            coupon.setUsedCount(0);
        }
        
        if (!save(coupon)) {
            throw new BusinessException("创建优惠券失败");
        }
        
        log.info("创建优惠券成功: {}", coupon.getId());
        return coupon.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateCoupon(String id, CouponDTO couponDTO) {
        Coupon existingCoupon = getById(id);
        if (existingCoupon == null) {
            throw new BusinessException("优惠券不存在");
        }
        
        // 检查是否可以修改
        if (existingCoupon.getReceivedCount() != null && existingCoupon.getReceivedCount() > 0) {
            throw new BusinessException("已有用户领取的优惠券不能修改");
        }
        
        validateCouponData(couponDTO);
        
        Coupon coupon = new Coupon();
        BeanUtils.copyProperties(couponDTO, coupon);
        coupon.setId(id);
        coupon.setUpdateBy(UserContext.getUserId());
        
        boolean result = updateById(coupon);
        if (result) {
            log.info("更新优惠券成功: {}", id);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteCoupon(String id) {
        Coupon coupon = getById(id);
        if (coupon == null) {
            throw new BusinessException("优惠券不存在");
        }
        
        // 检查是否可以删除
        if (coupon.getReceivedCount() != null && coupon.getReceivedCount() > 0) {
            throw new BusinessException("已有用户领取的优惠券不能删除");
        }
        
        boolean result = removeById(id);
        if (result) {
            log.info("删除优惠券成功: {}", id);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteCouponsBatch(List<String> ids) {
        // 批量检查是否可以删除
        List<Coupon> coupons = listByIds(ids);
        for (Coupon coupon : coupons) {
            if (coupon.getReceivedCount() != null && coupon.getReceivedCount() > 0) {
                throw new BusinessException("优惠券 " + coupon.getName() + " 已有用户领取，不能删除");
            }
        }
        
        boolean result = removeByIds(ids);
        if (result) {
            log.info("批量删除优惠券成功: {}", ids);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateCouponStatus(String id, Integer status) {
        Coupon coupon = new Coupon();
        coupon.setId(id);
        coupon.setStatus(status);
        coupon.setUpdateBy(UserContext.getUserId());
        
        boolean result = updateById(coupon);
        if (result) {
            log.info("更新优惠券状态成功: {} -> {}", id, status);
        }
        
        return result;
    }

    @Override
    public List<CouponVO> getHotCoupons(Integer limit) {
        LambdaQueryWrapper<Coupon> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Coupon::getIsDeleted, 0)
               .eq(Coupon::getStatus, 1) // 进行中
               .le(Coupon::getStartTime, LocalDateTime.now())
               .ge(Coupon::getEndTime, LocalDateTime.now())
               .orderByDesc(Coupon::getReceivedCount)
               .last("LIMIT " + (limit != null ? limit : 10));
        
        List<Coupon> coupons = list(wrapper);
        return coupons.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    /**
     * 验证优惠券数据
     */
    private void validateCouponData(CouponDTO couponDTO) {
        if (!StringUtils.hasText(couponDTO.getName())) {
            throw new BusinessException("优惠券名称不能为空");
        }
        
        if (couponDTO.getType() == null || couponDTO.getType() < 1 || couponDTO.getType() > 3) {
            throw new BusinessException("优惠券类型无效");
        }
        
        if (couponDTO.getStartTime() != null && couponDTO.getEndTime() != null &&
            couponDTO.getStartTime().isAfter(couponDTO.getEndTime())) {
            throw new BusinessException("开始时间不能晚于结束时间");
        }
        
        if (couponDTO.getType() == 1 && (couponDTO.getAmount() == null || 
            couponDTO.getAmount().compareTo(java.math.BigDecimal.ZERO) <= 0)) {
            throw new BusinessException("满减券金额必须大于0");
        }
        
        if (couponDTO.getType() == 2 && (couponDTO.getDiscountRate() == null ||
            couponDTO.getDiscountRate().compareTo(java.math.BigDecimal.ZERO) <= 0 ||
            couponDTO.getDiscountRate().compareTo(java.math.BigDecimal.ONE) >= 0)) {
            throw new BusinessException("折扣券折扣率必须在0-1之间");
        }
    }

    /**
     * 转换为VO
     */
    private CouponVO convertToVO(Coupon coupon) {
        CouponVO vo = new CouponVO();
        BeanUtils.copyProperties(coupon, vo);
        
        // 设置状态名称
        vo.setStatusName(getStatusName(coupon.getStatus()));
        vo.setTypeName(getTypeName(coupon.getType()));
        
        // 计算剩余数量
        if (coupon.getTotalCount() != null && coupon.getTotalCount() > 0) {
            int received = coupon.getReceivedCount() != null ? coupon.getReceivedCount() : 0;
            vo.setRemainingCount(Math.max(0, coupon.getTotalCount() - received));
        }
        
        // 计算使用率
        if (coupon.getReceivedCount() != null && coupon.getReceivedCount() > 0) {
            int used = coupon.getUsedCount() != null ? coupon.getUsedCount() : 0;
            vo.setUsageRate((double) used / coupon.getReceivedCount());
        }
        
        return vo;
    }

    private String getStatusName(Integer status) {
        if (status == null) return "未知";
        switch (status) {
            case 0: return "未开始";
            case 1: return "进行中";
            case 2: return "已结束";
            case 3: return "已停用";
            default: return "未知";
        }
    }

    private String getTypeName(Integer type) {
        if (type == null) return "未知";
        switch (type) {
            case 1: return "满减券";
            case 2: return "折扣券";
            case 3: return "免邮券";
            default: return "未知";
        }
    }
}
